package net.freebytes.ssmp.util;

import net.freebytes.ssmp.config.EnvironmentProperties;
import net.freebytes.ssmp.entity.User;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.util.Assert;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

/**
 * @version 1.0
 * @author: 千里明月
 * @date: 2019/7/8 9:38
 */
public class CommonUtil {


    public static void downloadFile(HttpServletResponse response, String path) {
        path = EnvironmentProperties.getUploadPath() + path;
        if (!new File(path).exists()) {
            return;
        }
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        String name = FileStorer.getFileNameFromUrl(FileStorer.getCanonicalPath(path));
        try (
                FileInputStream inputStream = new FileInputStream(path)
        ) {
            response.setHeader("Content-disposition", String.format("attachment; filename=" + new String(name.getBytes("gbk"), "iso8859-1")));
            IOUtils.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("AlibabaRemoveCommentedCode")
    public static void previewFile(HttpServletResponse response, String path) {
        path = EnvironmentProperties.getUploadPath() + path;
        if (!new File(path).exists()) {
            return;
        }
        //noinspection AlibabaRemoveCommentedCode,AlibabaRemoveCommentedCode
        try (
                InputStream inputStream = new FileInputStream(path)
        ) {
            String contentType = Files.probeContentType(Paths.get(path));
            response.setContentType(contentType);
            IOUtils.copy(inputStream, response.getOutputStream());
            //response.flushBuffer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static HashMap<String, Object> getMap(String key, Object value) {
        HashMap<String, Object> map = new HashMap<>(4);
        map.put(key, value);
        return map;
    }

    public static HashMap<String, Object> getMap() {
        HashMap<String, Object> map = new HashMap<>(16);
        return map;
    }

    /**
     * 加盐加密
     *
     * @param srcPwd    原始密码
     * @param saltValue 盐值
     */
    public static String salt(Object srcPwd, String saltValue) {
        return new Sha256Hash(srcPwd, saltValue, 20).toString();
    }

    public static HashMap<String, String> getStringMap(String key, String value) {
        HashMap<String, String> map = new HashMap<>(2);
        map.put(key, value);
        return map;
    }

    public static User currentUser() {
        Subject subject = SecurityUtils.getSubject();
        Object principal = subject.getPrincipal();
        if (principal == null) {
            return null;
        }
        User user = (User) subject.getPrincipal();
        user.setPassword(null);
        user.setSalt(null);
        return user;
    }

    /**
     * 文件名中只能包含字母、数字、中文、._-、符号，首字符只能为字母、数字或中文，且大小只能在256个字符内
     *
     * @param fileName
     * @return
     */
    public static boolean isValidFileName(String fileName) {
        return StringUtils.isNotBlank(fileName) && fileName.length() < 256 && fileName.matches("[a-zA-Z0-9\\u4e00-\\u9fa5][a-zA-Z0-9\\u4e00-\\u9fa5@_\\-、]*");
    }

    public static boolean isValidFileds(String... fileds) {
        for (String filed : fileds) {
            boolean b = StringUtils.isNotBlank(filed) && filed.length() < 256 && filed.matches("[a-zA-Z0-9\\u4e00-\\u9fa5][a-zA-Z0-9\\u4e00-\\u9fa5@_\\-、]*");
            if (!b) {
                return false;
            }
        }
        return true;
    }

    public static boolean isBlankString(String... fileds) {
        for (String filed : fileds) {
            if (StringUtils.isBlank(filed)) {
                return true;
            }
        }
        return false;
    }

    public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) {
        if (map == null) {
            return null;
        }
        Object obj = null;
        try {
            obj = clazz.newInstance();

            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                int mod = field.getModifiers();
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                field.setAccessible(true);
                Object value = map.get(field.getName());
                //给obj对象的field设置value值
                field.set(obj, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) obj;
    }


    /**
     * 递归地删除一个文件或目录
     *
     * @param dir
     * @return
     */
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDir(file);
                }
            }
        }
        return dir.delete();
    }

    /**
     * 校验host是否域名而非ip
     *
     * @author 千里明月
     * @date 2021/7/20
     **/
    public static boolean validateHost(String host) {
        int i = host.indexOf(".");
        if (i <= 0) {
            return false;
        }
        char[] chars = new char[host.length()];
        host.getChars(0, host.length(), chars, 0);
        boolean remark = false;
        for (char aChar : chars) {
            //假如host不是纯数字组成的IP，即host是用有英文字符组成的域名
            if (aChar != 46 && (aChar > 57 || aChar < 48)) {
                remark = true;
                break;
            }
        }
        return remark;
    }


    /**
     * 随机生成指定位数的字符串
     *
     * @author 千里明月
     * @date 2021/7/20
     **/
    public static String getRandomString(int length) {
        Assert.isTrue(length > 0, "输入长度必须大于0");
        String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            //62个字符
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    public static String isImage(InputStream inputStream) {//该方法适用的图片格式为 bmp/gif/jpg/png
        try {
            BufferedImage image = ImageIO.read(inputStream);
            if (image != null) {
                double width = Math.ceil(image.getWidth());
                double height = Math.ceil(image.getHeight());
                return (int) width + "*" + (int) height;
            }
            return null;
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    public static String generateUuid() {
        return UUID.randomUUID().toString().replace("-", "");
    }
}
